package view.actionListeners;

import java.awt.Color;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;

import utils.ActivateButton;
import view.DisplayManager;
import view.displayManagers.GameDisplayTool.ClickedPiece;
import controller.HumanControlledGame;

/**
 * Class implements an action listener for board button, used in two players game mode
 */
public class TwoPlayersListener implements ActionListener {

	// members
	
	private int boardSize; // chess board's size
	private Color mark; // color to mark reachable position	
	private List<JButton> boardButtons; // list of all board buttons	
	protected ClickedPiece lastToBeClicked; // last piece the user clicked on	
	protected DisplayManager displayManager; // object to manage board display
	protected HumanControlledGame gameManager; // system's game manager
	protected ActivateButton buttonActivator; // used to switch button on or off
	
	// protected methods
	
	/**
	 * Marks all board buttons that the piece at the clicked button can reach to
	 * @param row- row index of clicked button
	 * @param col- column index of clicked button
	 */
	protected void findMoves(int row, int col) {

		// get reachable positions from clicked button		
		List<Point> moveList = gameManager.getNextMove(new Point(row, col));
		
		// check if there are any reachable positions
		if (moveList.isEmpty()) {
			// no reachable positions
			return;
		}
		
		// update last-to-be-clicked button's position
		lastToBeClicked.setPosition(row, col);

		// refresh board display 
		displayManager.refreshBoardDisplay();
		
		// update last-to-be-clicked button's move list
		lastToBeClicked.getMoveList().clear();
		lastToBeClicked.getMoveList().addAll(moveList);
		
		// mark all reachable positions
		for (Point currPosition : moveList) {
			
			// get button matching current position on board			
			JButton currBtn = boardButtons.get((currPosition.x-1)*boardSize + currPosition.y-1); // convert row-column index to linear index
			// mark button
			currBtn.setBackground(mark);
		}
	}
	
	/**
	 * Returns position of the clicked board button
	 * @param event- action event object
	 * @return position of clicked board button
	 */
	protected Point getButtonPosition(ActionEvent event) {
		// get clicked button's index
		String command = event.getActionCommand();
		int index = Integer.parseInt(command);
		
		// calculate board entry of clicked button
		int row = (index / boardSize) + 1;
		int col = (index % boardSize) + 1;
		
		// return button position
		return new Point(row, col);
	}
	
	/**
	 * Moves piece at last-to-be-clicked button to clicked position. 
	 * @param clickedPosition- position of clicked button
	 * @return True if could make the move, False if not
	 */
	protected boolean makeMove(Point clickedPosition) {
		
		// check if clicked button is a destination for last-to-be-clicked button		
		if (!lastToBeClicked.getMoveList().contains(clickedPosition)) {
			
			// cannot move to clicked piece 
			return false;
		}
		
		// make move
		boolean canMove = gameManager.makeMoveHuman(lastToBeClicked.getPosition(), clickedPosition);
		
		// check if could move
		if (!canMove) {
			
			// could not move
			return false;
		}
		
		// refresh board display after move
		displayManager.refreshBoardDisplay();
		
		// clear last-to-be-clicked buttom's moves
		lastToBeClicked.getMoveList().clear();
		
		// move made successfully
		return true;
	}
	
	// public methods
	
	/**
	 * Constructor- creates a new two-players-listener object
	 * @param boardSize- game board's size
	 * @param mark- color to mark reachable positions
	 * @param displayManager- used to manage board display
	 * @param gameManager- reference to game manager
	 * @param lastToBeClicked- holds data about last-to-be-clicked button
	 * @param boardButtons- board buttons
	 * @param buttonActivator- used to switch board buttons on or off
	 */
//	public TwoPlayersListener(int boardSize, Color mark, DisplayManager displayManager, Controller gameManager, ClickedPiece lastToBeClicked, List<JButton> boardButtons,  ActivateButton buttonActivator) { // TOOD DEUB!!!
	public TwoPlayersListener(int boardSize, Color mark, DisplayManager displayManager, HumanControlledGame gameManager, ClickedPiece lastToBeClicked, List<JButton> boardButtons,  ActivateButton buttonActivator) {
		
		// set members according to given values
		this.boardSize = boardSize;
		this.mark = mark;
		this.displayManager = displayManager;
		this.gameManager = gameManager;
		this.lastToBeClicked = lastToBeClicked;
		this.boardButtons = boardButtons;
		this.buttonActivator = buttonActivator;
	}
	
	/**
	 * When button is clicked, asks game manager for list of reachable positions of piece at clicked button.
	 * If list is empty, nothing is done.
	 * Otherwise, last-to-be-clicked button is updated to this clicked button and piece's reachable positions are marked
	 */
	@Override
	public void actionPerformed(ActionEvent arg0) {
		
		// check if buttons are activated
		if (!buttonActivator.isActivated()) {
			// not activated, do nothing
			return;
		}
		
		// get clicked button position on board
		Point clickedPosition = getButtonPosition(arg0); 
		
		// check if should make move
		if (makeMove(clickedPosition)) {
			
			// move made, check if game is over
			if (gameManager.isCheckmate()) {
				displayManager.gameOver("Well done, checkmate!");
				return;
			}
			
			// move made, check if Stalemate
			if (gameManager.isStalemate()) {				
				// game is over
				displayManager.gameOver("Well done, stalemate!");
				return;				
			}
			
			// game not over, check if attacked King is threatened
			if (gameManager.isCheck()) {
				// notify user
				displayManager.notifyCheck();
				return;
			}
			
		} else {
			// no move to make
			findMoves(clickedPosition.x, clickedPosition.y);
		}
		
		return;
	}
}